package com.timber.util;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.plaf.metal.*;
import pv.jfcx.*;

/**
 *
 * wrapper for JPVTable
 * provides methods for managing rows of data
 */
public class SLTable extends JPVTable
{
  protected int		visibleRowCount = 8;
  protected boolean	waitCursorInitialized = false;
  protected Component	glassPane;


  public SLTable()
  {
    this( new SLDefaultTableModel() );
  }

  public SLTable( SLTableModel tm )
  {
    super( tm );
    setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
    setCellSelectionEnabled( false );
    setColumnSelectionAllowed( false );
    setRowSelectionAllowed( true );
    setSelectionMode( ListSelectionModel.SINGLE_INTERVAL_SELECTION );
  }

  /**
   **  This method will create default columns for the table from
   **  the data model using the getColumnCount() and getColumnClass() methods
   **  defined in the TableModel interface.
   **  <p>
   **  This method will clear any exsiting columns before creating the
   **  new columns based on information from the model.
   **
   **  @see     #getAutoCreateColumnsFromModel
   **/
  public void createDefaultColumnsFromModel()
  {
    Font font = getFont();
    if( font == null )
    {
      font = MetalLookAndFeel.getUserTextFont();
      setFont( font );
    }

    FontMetrics tblFm = getFontMetrics( font );
    SLTableModel tm = ( SLTableModel )getModel();
    Vector cols = tm.getColumnList();

    if( tm != null )
    {
      // Remove any current columns
      TableColumnModel cm = getColumnModel();
      cm.removeColumnModelListener( this );
      while( cm.getColumnCount() > 0 )
	cm.removeColumn( cm.getColumn( 0 ) );

      // Create new columns from the data model info
      for( int i = 0; i < tm.getColumnCount(); i++ )
      {
	SLColumnDefinition cd = ( ( SLColumnDefinition )cols.elementAt( i ) );
// 	if( cd.isVisible() == false )
// 	  continue;
	int colWidth = ( cd.getDisplayWidth() * tblFm.stringWidth( "W" ) ) + 6;
	int colType = cd.getColType();
	TableCellRenderer tcr = cd.getRenderer();
	TableCellEditor tce = cd.getEditor();

	TableColumn newColumn = new TableColumn( i );
	newColumn.setPreferredWidth( colWidth );
	newColumn.setWidth( colWidth );
	newColumn.setIdentifier( new Integer( cd.getId() ) );
	if( tcr != null )
	  newColumn.setCellRenderer( tcr );
	else
	  newColumn.setCellRenderer( ( colType == JPVTable.NONE ) ? null : new PVTableRenderer( colType ) );

	if( tce != null )
	  newColumn.setCellEditor( tce );
	else
	  newColumn.setCellEditor( ( colType == JPVTable.NONE ) ? null : new PVTableEditor( colType ) );

	addColumn( newColumn );
      }

      cm.addColumnModelListener( this );
    }
  }

  /**
   * Implement table header tool tips.
   */
  /*protected JTableHeader createDefaultTableHeader()
  {
    return new JTableHeader(columnModel)
      {
	public String getToolTipText(MouseEvent e)
	{
	  SLTableModel tm = ( SLTableModel )getModel();
	  //Vector cols = tm.getColumnList();

	  //String tip = null;
	  java.awt.Point p = e.getPoint();
	  int index = columnModel.getColumnIndexAtX(p.x);
	  int realIndex = columnModel.getColumn(index).getModelIndex();
	  //return ((SLColumnDefinition)cols.elementAt(realIndex)).getDisplayLabel();
	  return tm.getHeaderToolTip( realIndex );
	}
      };
  }
  */

  /**
   *   Implement table cell tool tips.
   */
   public String getToolTipText(MouseEvent e)
  {
    //String tip = null;
    java.awt.Point p = e.getPoint();
    //int rowIndex = rowAtPoint(p);
    int colIndex = columnAtPoint(p);
    int realColumnIndex = convertColumnIndexToModel(colIndex);
    SLTableModel tm = ( SLTableModel )getModel();

    // for now just return header toolTip
    return tm.getHeaderToolTip( realColumnIndex );

    //  return unformated value
    //return tm.getValueAt( rowIndex, realColumnIndex ).toString();
  }

  public int getVisibleRowCount()
  {
    return visibleRowCount;
  }

  public void setVisibleRowCount( int cnt )
  {
    visibleRowCount = cnt;
    int vpWidth;
    int vpHeight;
    int tblWidth = getPreferredSize().width;
    if( tblWidth > 0 && tblWidth < preferredViewportSize.width )
      vpWidth = tblWidth;
    else
      vpWidth = preferredViewportSize.width;

    vpHeight = ( getRowHeight() + getRowMargin() ) * visibleRowCount;
    Dimension vpDim = new Dimension( vpWidth, vpHeight );
    preferredViewportSize = vpDim;
    updateUI();
  }

  /**
   *	copy selected rows to clipboard and
   *	locale copy vector, <i>copyV</i>
   */
  public int copySelected()
  {
    int[] rows = getSelectedRows();

    if( rows.length <= 0 )
      return 0;

    SLTableModel tm = ( SLTableModel )getModel();

    return tm.copyTableRows( rows, true );
  }

  public int deleteSelected()
  {
    int[] rows = getSelectedRows();

    if( rows.length <= 0 )
      return 0;

    SLTableModel tm = ( SLTableModel )getModel();

    return tm.deleteTableRows( rows );
  }

  protected boolean deleteKey( int r, int c )
  {
    if( !getEnableDeleteKey() )
      return false;

    deleteSelected();

    int maxRow = getRowCount() - 1;
    if( maxRow >= 0 )
    {
      int focusRow = getFocusRow();
      if( focusRow <= maxRow )
	setRowSelectionInterval( focusRow, focusRow );
      else
	setRowSelectionInterval( maxRow, maxRow );
    }

    return true;
  }

  /**
   *  Sets the editability of a column identified by its column ID
   *
   *  @param colId the internal column identifier
   *  @param val true makes column editable, false makes column not editable
   */
  public void setColumnEditable( int colId, boolean val )
  {
    getSLTableModel().setColumnEditable( colId, val );
  }

  /**
   *  Sets the editability of a column specified by its absolute position
   *
   *  @param colNum the column position
   *  @param val true makes column editable, false makes column not editable
   */
  public void setColumnEditableByColNum( int colNum, boolean val )
  {
    getSLTableModel().setColumnEditableByColNum( colNum, val );
  }

  /**
   *  Returns the table model as a SLTableModel
   */
  public SLTableModel getSLTableModel()
  {
    SLTableModel tm = ( SLTableModel )getModel();
    return tm;
  }

  /**
   *  Overrides super class so we can display wait cursor during click sorting.
   */
  protected boolean headerMouse( MouseEvent e )
  {
    boolean shouldDoWaitCursor = false;
    if( e.getID() == MouseEvent.MOUSE_CLICKED && SwingUtilities.isLeftMouseButton( e ) )
    {
      shouldDoWaitCursor = true;
      doWaitCursor();
    }

    boolean ret = super.headerMouse( e );

    if( shouldDoWaitCursor )
    {
      undoWaitCursor();
    }

    return ret;
  }

  /**
   *  Displays the wait cursor by making the parent JFrame or JDialog glassPane
   *  visible (if there is one). A lazy initialization is done the first time
   *  this method is called to set the cursor of the glassPane to the wait cursor.
   */
  public void doWaitCursor()
  {
    if( waitCursorInitialized == false )
    {
      glassPane = Util.getGlassPaneForComponent( this );
      if( glassPane != null )
      {
	glassPane.addMouseListener( new MouseAdapter() {} );
	glassPane.addKeyListener( new KeyAdapter() {} );
	glassPane.setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR ) );
      }

      waitCursorInitialized = true;
    }

    if( glassPane != null )
      glassPane.setVisible( true );
  }

  /**
   *  Reverses the effect of doWaitCursor.
   */
  public void undoWaitCursor()
  {
    if( glassPane != null )
      glassPane.setVisible( false );
  }
}
